package discard.kv;

import java.util.Map;

import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.MemoryUnit;

//import org.ehcache.config.CacheConfiguration;
//import org.ehcache.config.builders.CacheConfigurationBuilder;
//import org.ehcache.config.builders.ResourcePoolsBuilder;
//import org.ehcache.config.units.MemoryUnit;

import hyl.core.MyFun;
import hyl.core.data.ICacheConfig;

/**
 * ehcache 组件 配置参数
 * 
 * @author 37798955@qq.com
 *
 */
public class ConfigKvCache implements ICacheConfig {

	/**
	 * 堆缓存大小 单位KB
	 */
	public int HEAP_CACHE_SIZE = 10;

	/**
	 * 堆外缓存大小 单位MB
	 */
	public int OFF_HEAP_CACHE_SIZE = 20;

	/**
	 * 可缓存的最大对象大小 单位Kb
	 */
	public long HEAP_MAX_Object_SIZE = 1L;

	/**
	 * 统计对象大小时对象图遍历深度
	 */
	public long HEAP_MAX_Object_GRAPH = 1000L;
	/**
	 * ehcache缓存超时时间 单位秒
	 */
	public int EHCACHE_TTL = 120;
	/**
	 * 磁盘文件路径
	 */
	public String DISK_CACHE_DIR;
	/**
	 * 磁盘缓存大小 单位MB
	 */
	public long DISK_CACHE_SIZE = 10;
	private ResourcePoolsBuilder RPB = null;
	public Object CACHECONF = null;

	public ConfigKvCache(Map<String, String> conf) {
		// 可缓存的最大对象大小
		setHEAP_MAX_Object_SIZE(conf.get("objectmaxsize_k"));
		// 统计对象大小时对象图遍历深度
		setHEAP_MAX_Object_GRAPH(conf.get("objectmaxgraph"));
		// 堆外缓存大小 单位MB
		setOFF_HEAP_CACHE_SIZE(conf.get("offheapsize_m")); // 堆外缓存大小 单位MB
		// 堆缓存大小 单位KB
		setHEAP_CACHE_SIZE(conf.get("heapsize"));
		// ehcache缓存超时时间 单位秒
		setEHCACHE_TTL(conf.get("ttl"));
		// 磁盘缓存大小 单位MB
		setDISK_CACHE(conf.get("diskdir"), conf.get("disksize_m"));
		RPB = ResourcePoolsBuilder.heap(HEAP_CACHE_SIZE).offheap(OFF_HEAP_CACHE_SIZE, MemoryUnit.MB);
		if (MyFun.isEmpty(DISK_CACHE_DIR)) {
			RPB.disk(DISK_CACHE_SIZE, MemoryUnit.GB);
		} // 磁盘
	}

	private void afterConf(CacheConfigurationBuilder<?, ?> build) {
		// 缓存自创建日期起至失效时的间隔时间x；
		// build.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(EHCACHE_TTL)));
		// 缓存创建以后，最后一次访问缓存的日期至失效之时的时间间隔y；
		// build.withExpiry(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofSeconds(EHCACHE_TTL)));
		// 如果仅有timeToLiveSeconds那么自创建时间开始 间隔x后缓存失效；
		// 如果没有timeToLiveSeconds那么自最后一次访问缓存间隔y后 缓存失效；
		// 如果既有timeToLiveSeconds也有timeToIdleSeconds那么取最小数算作间隔时间；min(x,y)
		// 经过测试其计算原则是： 若自创建缓存后一直都没有访问缓存，那么间隔x后失效，
		// 若自创建缓存后有N次访问缓存，那么计算(最后一次访问缓存时间+y)
		// 即：按照timeToIdleSeconds计算，但总存活时间不超过 y;
		build.withSizeOfMaxObjectGraph(HEAP_MAX_Object_GRAPH); // 统计对象大小时对象图遍历深度
		build.withSizeOfMaxObjectSize(HEAP_MAX_Object_SIZE, MemoryUnit.KB);// 可缓存的最大对象大小
	}

	@SuppressWarnings("unchecked")
	public <K, V> CacheConfiguration<K, V> getCacheConf(Class<K> k, Class<V> V) {
		if (CACHECONF == null) {
		CacheConfigurationBuilder<K, V> build = CacheConfigurationBuilder.newCacheConfigurationBuilder(k, V, RPB);
			// 缓存淘汰策略 默认策略是LRU（最近最少使用）。你可以设置为FIFO（先进先出）或是LFU（较少使用）。
			// 设置堆外储存大小(内存存储) 超出offheap的大小会淘汰规则被淘汰
			// 配置磁盘持久化储存(硬盘存储)用来持久化到磁盘,这里设置为false不启用
			afterConf(build);
			// 创建持久性服务使用缓存来存储在磁盘上的数据
			// 通过持久性服务建造一个id缓存——
			// 这将产生一个更具体的类型:PersistentUserManagedCache
			CACHECONF = build.build();
		}
		return (CacheConfiguration<K, V>) CACHECONF;
	}

	public void setHEAP_CACHE_SIZE(String b) {
		if (MyFun.isEmpty(b))
			HEAP_CACHE_SIZE=10;
		try {
			HEAP_CACHE_SIZE = MyFun.str2int(b);
		} catch (Exception e) {
		}
	}

	public void setOFF_HEAP_CACHE_SIZE(String b) {

		if (MyFun.isEmpty(b))
			OFF_HEAP_CACHE_SIZE=100;
		try {
			OFF_HEAP_CACHE_SIZE = MyFun.str2int(b);
		} catch (Exception e) {
		}
	}

	public void setHEAP_MAX_Object_SIZE(String b) {
		if (MyFun.isEmpty(b))
			HEAP_MAX_Object_SIZE=1024;
		try {
			HEAP_MAX_Object_SIZE = MyFun.str2long(b);
		} catch (Exception e) {
		}
	}

	public void setHEAP_MAX_Object_GRAPH(String b) {

		if (MyFun.isEmpty(b))
			HEAP_MAX_Object_GRAPH=1000;
		try {
			HEAP_MAX_Object_GRAPH = MyFun.str2long(b);
		} catch (Exception e) {
		}
	}

	public void setEHCACHE_TTL(String b) {
		if (MyFun.isEmpty(b))
			EHCACHE_TTL =0;
		try {
			EHCACHE_TTL = MyFun.str2int(b);
		} catch (Exception e) {
		}
	}

	public void setDISK_CACHE(String dir, String size) {
		if (MyFun.isEmpty(dir))
			return;

		int c = MyFun.str2int(size);
		if (c < 0)
			c=100;
		DISK_CACHE_SIZE = c;
		DISK_CACHE_DIR = dir;
	}

}
